package com.clementheliou.cheliou.web.util.number;

import org.springframework.stereotype.Component;

/**
 * Utilities about numbers.
 * 
 * @author Clément HELIOU (clement.heliou@gmail.com)
 * @see {@link Component};
 * @since 1.0
 */
@Component
public class NumberUtils {

	/**
	 * Gets the digits number contained in the given integer. The algorithm that
	 * we used is based on the {@link Math#log10(double)} method that is twice
	 * faster than the {@link String#length()} one.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param integerValue the integer value to analyze.
	 * @return the digits number of the given integer.
	 * @since 1.0
	 */
	public int getIntegerDigitsNumber(int integerValue) {
		final int log10 = (int) Math.log10(integerValue);
		return ((log10 < 0) ? 0 : log10) + 1;
	}

	/**
	 * Gets the sum of the given integer's digits.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param integerValue the integer value to analyze.
	 * @return the resulting sum.
	 * @since 1.0
	 */
	public int getSumOfIntegerDigits(int integerValue) {
		return getSumOfIntegerDigits(integerValue, getIntegerDigitsNumber(integerValue));
	}

	/**
	 * Recursive method used to retrieve the expected result for the
	 * {@link #getSumOfIntegerDigits(int)} public method. It divides the
	 * <tt>integerValue</tt> param by <tt>10^digitsNumber</tt> and calls itself
	 * with the remainder while the <tt>digitsNumber</tt> param isn't equals to
	 * one.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param integerValue the integer value to analyze.
	 * @param digitsNumber the digits number contained in the integer value.
	 * @return the of the digits contained in the given integer.
	 * @since 1.0
	 */
	private int getSumOfIntegerDigits(int integerValue, int digitsNumber) {
		if (digitsNumber == 1) {
			return integerValue;
		}

		final int divider = (int) Math.pow(10, digitsNumber - 1);
		final int remainder = integerValue % divider;

		return (integerValue / divider) + getSumOfIntegerDigits(remainder, digitsNumber - 1);
	}
}
